package dk.kapetanovic.jaft.transaction;


import java.io.File;
import java.util.ArrayList;

import dk.kapetanovic.jaft.exception.InconsistentStateException;
import dk.kapetanovic.jaft.exception.TransactionException;
import dk.kapetanovic.jaft.transaction.fac.DefaultTransactionFactory;
import dk.kapetanovic.jaft.transaction.fac.OutputTransactionFactory;
import dk.kapetanovic.jaft.transaction.fac.RecoveryTransactionFactory;
import dk.kapetanovic.jaft.transaction.fac.TransactionFactory;

public class TransactionManagerImpl implements TransactionManager {
	
	public static TransactionManager getDefaultInstance(File backupDir) {
		TransactionFactory fac = new DefaultTransactionFactory();
		TransactionManager tm = new TransactionManagerImpl(backupDir, fac);
		fac.setTransactionManager(tm);
		return tm;
	}
	
	public static TransactionManager getOutputInstance(File backupDir, File journalDir) {
		TransactionFactory fac = new OutputTransactionFactory(journalDir);
		TransactionManager tm = new TransactionManagerImpl(backupDir, fac);
		fac.setTransactionManager(tm);
		return tm;
	}
	
	public static TransactionManager getRecoveryInstance(File backupDir, File journalDir) {
		TransactionFactory fac = new RecoveryTransactionFactory(journalDir);
		TransactionManager tm = new TransactionManagerImpl(backupDir, fac);
		fac.setTransactionManager(tm);
		return tm;
	}
	
	public static TransactionManager recovery(File backupDir, File journalDir) {
		TransactionManager tm = getRecoveryInstance(backupDir, journalDir);
		Transaction trans;
		try {
			trans = tm.beginTransaction();
			if(trans != null)
				trans.rollback();
		} 
		catch (Exception e) {
			e.printStackTrace();
		}
		
		return getOutputInstance(backupDir, journalDir);
	}
	
	private File backup;
	private ArrayList<Transaction> transactions = new
		ArrayList<Transaction>();
	private TransactionFactory factory;
	
	public TransactionManagerImpl(File backupDir, TransactionFactory fac) {
		this.backup = backupDir;
		this.factory = fac;
	}

	@Override
	public synchronized Transaction beginTransaction() throws TransactionException {
		Transaction trans = factory.createTransaction();
		transactions.add(trans);
		return trans;
	}

	@Override
	public synchronized void close() throws InconsistentStateException, TransactionException {
		int size = transactions.size();
		for(int i = 0; i < size; i++) {
			Transaction t = transactions.remove(i);
			if(t.isActive())
				t.rollback();
		}
	}

	@Override
	public File getBackupDir() {
		return backup;
	}
}
